package com.example.springboot.service;

import com.example.springboot.dto.SelfServicePointDTO;
import com.example.springboot.entity.SelfServicePoint;
import com.example.springboot.mapper.SelfServicePointMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;

@Service
public class SelfServicePointService {

    private static final Logger logger = LoggerFactory.getLogger(SelfServicePointService.class);

    @Autowired
    private SelfServicePointMapper selfServicePointMapper;

    @Autowired
    private OSSService ossService;

    public List<SelfServicePoint> getSelfServicePoints(String role, String username) {
        String decodedUsername = decodeUsername(username);
        validateInput(role, decodedUsername);

        try {
            logger.info("Fetching self-service points for role: {}, username: {}", role, decodedUsername);
            if ("super".equals(role)) {
                logger.info("Super admin access: retrieving all self-service points");
                List<SelfServicePoint> points = selfServicePointMapper.findAll();
                logger.info("Retrieved {} self-service points", points.size());
                return points;
            } else {
                logger.info("Non-super role access: retrieving self-service points by admin ID");
                Integer adminId = getAdminId(decodedUsername);
                List<SelfServicePoint> points = selfServicePointMapper.findByAdminId(adminId);
                logger.info("Retrieved {} self-service points for adminId: {}", points.size(), adminId);
                return points;
            }
        } catch (Exception e) {
            logger.error("Failed to fetch self-service points for role: {}, username: {}", role, decodedUsername, e);
            throw new RuntimeException("获取自助点列表失败: " + e.getMessage(), e);
        }
    }

    public SelfServicePoint createSelfServicePoint(SelfServicePointDTO dto, MultipartFile posterFile, String role, String username) throws Exception {
        String decodedUsername = decodeUsername(username);
        validateInput(role, decodedUsername);

        SelfServicePoint point = new SelfServicePoint();
        point.setName(dto.getName());
        point.setAddress(dto.getAddress());
        point.setContactNumber(dto.getContactNumber());
        point.setIsActive(dto.getActive() != null ? dto.getActive() : true);
        point.setLatitude(dto.getLatitude());
        point.setLongitude(dto.getLongitude());
        point.setCreatedAt(Timestamp.valueOf(LocalDateTime.now()));

        try {
            if ("ADMIN".equals(role) && !"super".equals(role)) {
                String adminRole = selfServicePointMapper.findAdminRoleByUsername(decodedUsername);
                if (adminRole == null) {
                    logger.error("No role found for username: {}", decodedUsername);
                    throw new IllegalArgumentException("管理员用户不存在或角色未定义");
                }
                if ("common".equals(adminRole)) {
                    Integer adminId = getAdminId(decodedUsername);
                    point.setAdminId(adminId);
                } else {
                    point.setAdminId(dto.getAdminId()); // super admin can specify adminId
                }
            } else if (!"super".equals(role)) {
                Integer adminId = getAdminId(decodedUsername);
                point.setAdminId(adminId);
            } else {
                point.setAdminId(dto.getAdminId()); // super admin can specify adminId
            }

            if (posterFile != null && !posterFile.isEmpty()) {
                String posterUrl = ossService.uploadImage(posterFile);
                point.setPoster(posterUrl);
            }

            selfServicePointMapper.insert(point);
            logger.info("Successfully created self-service point for username: {}", decodedUsername);
            return point;
        } catch (Exception e) {
            logger.error("Failed to create self-service point for role: {}, username: {}", role, decodedUsername, e);
            throw new RuntimeException("创建自助点失败: " + e.getMessage(), e);
        }
    }

    public SelfServicePoint updateSelfServicePoint(Integer pointId, SelfServicePointDTO dto, MultipartFile posterFile, String role, String username) throws Exception {
        String decodedUsername = decodeUsername(username);
        validateInput(role, decodedUsername);

        SelfServicePoint point = selfServicePointMapper.findById(pointId);
        if (point == null) {
            logger.warn("Self-service point not found for pointId: {}", pointId);
            throw new IllegalArgumentException("自助点不存在");
        }

        try {
            if ("ADMIN".equals(role) && !"super".equals(role)) {
                String adminRole = selfServicePointMapper.findAdminRoleByUsername(decodedUsername);
                if (adminRole == null) {
                    logger.error("No role found for username: {}", decodedUsername);
                    throw new IllegalArgumentException("管理员用户不存在或角色未定义");
                }
                if ("common".equals(adminRole)) {
                    Integer adminId = getAdminId(decodedUsername);
                    if (!point.getAdminId().equals(adminId)) {
                        logger.warn("Permission denied for username: {} to update pointId: {}", decodedUsername, pointId);
                        throw new IllegalArgumentException("无权限操作该自助点");
                    }
                }
            }

            point.setName(dto.getName());
            point.setAddress(dto.getAddress());
            point.setContactNumber(dto.getContactNumber());
            point.setIsActive(dto.getActive());
            point.setLatitude(dto.getLatitude());
            point.setLongitude(dto.getLongitude());

            if ("super".equals(role)) {
                point.setAdminId(dto.getAdminId()); // super admin can change adminId
            }

            if (posterFile != null && !posterFile.isEmpty()) {
                String posterUrl = ossService.uploadImage(posterFile);
                point.setPoster(posterUrl);
            }

            selfServicePointMapper.update(point);
            logger.info("Successfully updated self-service point {} for username: {}", pointId, decodedUsername);
            return point;
        } catch (Exception e) {
            logger.error("Failed to update self-service point {} for role: {}, username: {}", pointId, role, decodedUsername, e);
            throw new RuntimeException("更新自助点失败: " + e.getMessage(), e);
        }
    }

    public void deleteSelfServicePoint(Integer pointId, String role, String username) {
        String decodedUsername = decodeUsername(username);
        validateInput(role, decodedUsername);

        SelfServicePoint point = selfServicePointMapper.findById(pointId);
        if (point == null) {
            logger.warn("Self-service point not found for pointId: {}", pointId);
            throw new IllegalArgumentException("自助点不存在");
        }

        try {
            if ("ADMIN".equals(role) && !"super".equals(role)) {
                String adminRole = selfServicePointMapper.findAdminRoleByUsername(decodedUsername);
                if (adminRole == null) {
                    logger.error("No role found for username: {}", decodedUsername);
                    throw new IllegalArgumentException("管理员用户不存在或角色未定义");
                }
                if ("common".equals(adminRole)) {
                    Integer adminId = getAdminId(decodedUsername);
                    if (!point.getAdminId().equals(adminId)) {
                        logger.warn("Permission denied for username: {} to delete pointId: {}", decodedUsername, pointId);
                        throw new IllegalArgumentException("无权限删除该自助点");
                    }
                }
            }

            selfServicePointMapper.delete(pointId);
            logger.info("Successfully deleted self-service point {} for username: {}", pointId, decodedUsername);
        } catch (Exception e) {
            logger.error("Failed to delete self-service point {} for role: {}, username: {}", pointId, role, decodedUsername, e);
            throw new RuntimeException("删除自助点失败: " + e.getMessage(), e);
        }
    }

    private void validateInput(String role, String username) {
        if (username == null || username.trim().isEmpty()) {
            logger.error("Username is null or empty");
            throw new IllegalArgumentException("Username header is required");
        }
        if (role == null || role.trim().isEmpty()) {
            logger.error("Role is null or empty");
            throw new IllegalArgumentException("Role header is required");
        }
    }

    private Integer getAdminId(String username) {
        Integer adminId = selfServicePointMapper.findAdminIdByUsername(username);
        if (adminId == null) {
            logger.error("No admin ID found for username: {}", username);
            throw new IllegalArgumentException("无法获取管理员 ID，用户名可能不存在");
        }
        return adminId;
    }

    private String decodeUsername(String username) {
        if (username == null) {
            return null;
        }
        try {
            return URLDecoder.decode(username, StandardCharsets.UTF_8.name());
        } catch (Exception e) {
            logger.warn("Failed to decode username: {}, using original value", username, e);
            return username;
        }
    }
}